#ifndef _SERVERHPP_
#define _SERVERHPP_

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "InetAddr_1.hpp"

#include "log.hpp"

#include <string.h> //错误输出strerror函数
#include <error.h>
#include <stdlib.h>

#include <iostream>

#include "ErrorPrint.hpp"

const static uint16_t _defaultport = 8080;
const static int _defaultfd = -1;
namespace PracticeServer
{
    class Server
    {
    public:
        Server(uint16_t _outport = _defaultport) // 传入一个端口号
            : _sockfd(_defaultfd),
              _addr(_outport),
              _isrunning(false)
        {
        }

        void Init()
        {
            // 创建套接字
            // 创建bind

            _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd < 0)
            {
                LOG::LOG(LOG::LogLevel::FATAL) << "SOCKFD:" << strerror(errno);
                DIE(Error::SOCKFD_FAILED);
            }
            LOG::LOG(LOG::LogLevel::INFO) << "SOCKFD Success！ the sockfd is" << _sockfd << "\n";

            // 绑定bind
            if (::bind(_sockfd, _addr.IPv4UdpStructAddrToCONV(), _addr.IPv4UdpStructLen()) < 0)
            {
                LOG::LOG(LOG::LogLevel::FATAL) << "BIND:" << strerror(errno);
                DIE(Error::BIND_FAILED);
            }
            LOG::LOG(LOG::LogLevel::INFO) << "BIND Success！ the sockfd is" << _sockfd << "\n";
        }

        void Start()
        {
            _isrunning = true;

            while (true)
            {
                char _infobuffer[1024]; // 用来存储消息

                struct sockaddr_in _Ipv4StructForClient;
                socklen_t __Ipv4StructForClientLen = sizeof(_Ipv4StructForClient);

                ssize_t _n = ::recvfrom(
                    _sockfd,
                    _infobuffer, sizeof(_infobuffer),
                    0, (struct sockaddr *)&_Ipv4StructForClient, &__Ipv4StructForClientLen);

                if (_n > 0)
                {
                    InetAddr _clientaddr(_Ipv4StructForClient); // 客户端网址结构体
                    _infobuffer[_n] = 0;

                    std::string _clientinfo = "Ip from " + _clientaddr.HostIp() +
                                              "'Host' s PORT is" + std::to_string(_clientaddr.HostPort()) +
                                              ",and the Client' s info is" + _infobuffer;
                    LOG::LOG(LOG::LogLevel::DEBUG) << _clientinfo; // 以日志的方式打印出来

                    std::string _echofromServer = "ServerEcho#hello hello!";
                    ::sendto(
                        _sockfd,
                        _echofromServer.c_str(), _echofromServer.size(),
                        0, _clientaddr.IPv4UdpStructAddrToCONV(), _clientaddr.IPv4UdpStructLen());
                }
            }

            _isrunning = false;
        }

        ~Server()
        {
            if (_sockfd)
                ::close(_sockfd);
        }

    private:
        bool _isrunning;
        int _sockfd;
        InetAddr _addr;
    };
}

#endif